package org.crazyit.cloud.collapse;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.Future;

import com.netflix.config.ConfigurationManager;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapser.CollapsedRequest;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

public class CollapseTest {

	public static void main(String[] args) throws Exception {
		// 收集 1 秒内发生的请求，合并为一个命令执行
		ConfigurationManager.getConfigInstance().setProperty(
				"hystrix.collapser.default.timerDelayInMilliseconds", 1000);
		// 请求上下文
		HystrixRequestContext context = HystrixRequestContext
				.initializeContext();
		// 创建请求合并处理器
		MyHystrixCollapser c1 = new MyHystrixCollapser("Angus");
		MyHystrixCollapser c2 = new MyHystrixCollapser("Crazyit");
		MyHystrixCollapser c3 = new MyHystrixCollapser("Sune");
		MyHystrixCollapser c4 = new MyHystrixCollapser("Paris");
		// 异步执行
		Future<Person> f1 = c1.queue();
		Future<Person> f2 = c2.queue();
		Future<Person> f3 = c3.queue();
		Future<Person> f4 = c4.queue();
		System.out.println(f1.get());
		System.out.println(f2.get());
		System.out.println(f3.get());
		System.out.println(f4.get());
		context.shutdown();
	}

	/**
	 * 合并执行的命令类
	 * 
	 * @author 杨恩雄
	 *
	 */
	static class CollapserCommand extends HystrixCommand<Map<String, Person>> {
		// 请求集合，第一个类型是单个请求返回的数据类型，第二是请求参数的类型
		Collection<CollapsedRequest<Person, String>> requests;

		private CollapserCommand(
				Collection<CollapsedRequest<Person, String>> requests) {
			super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
					.asKey("ExampleGroup")));
			this.requests = requests;
		}

		@Override
		protected Map<String, Person> run() throws Exception {
			System.out.println("收集参数后执行命令，参数数量：" + requests.size());
			// 处理参数
			List<String> personNames = new ArrayList<String>();
			for(CollapsedRequest<Person, String> request : requests) {
				personNames.add(request.getArgument());
			}
			// 调用服务（此处模拟调用），根据名称获取Person的Map
			Map<String, Person> result = callService(personNames);
			return result;
		}
		
		// 模拟服务返回
		private Map<String, Person> callService(List<String> personNames) {
			Map<String, Person> result = new HashMap<String, Person>();
			for(String personName : personNames) {
				Person p = new Person();
				p.id = UUID.randomUUID().toString();
				p.name = personName;
				p.age = new Random().nextInt(30);
				result.put(personName, p);
			}
			return result;
		}
	}

	static class Person {
		String id;
		String name;
		Integer age;

		public String toString() {
			// TODO Auto-generated method stub
			return "id: " + id + ", name: " + name + ", age: " + age;
		}
	}

	/**
	 * 合并处理器
	 * 第一个类型为批处理返回的结果类型
	 * 第二个为单请求返回的结果类型
	 * 第三个是请求参数类型
	 * @author 杨恩雄
	 */
	static class MyHystrixCollapser extends
			HystrixCollapser<Map<String, Person>, Person, String> {

		String personName;

		public MyHystrixCollapser(String personName) {
			this.personName = personName;
		}

		@Override
		public String getRequestArgument() {
			return personName;
		}

		@Override
		protected HystrixCommand<Map<String, Person>> createCommand(
				Collection<CollapsedRequest<Person, String>> requests) {
			return new CollapserCommand(requests);
		}

		@Override
		protected void mapResponseToRequests(Map<String, Person> batchResponse,
				Collection<CollapsedRequest<Person, String>> requests) {
			// 让结果与请求进行关联
			for (CollapsedRequest<Person, String> request : requests) {
				// 获取单个响应返回的结果
				Person singleResult = batchResponse.get(request.getArgument());
				// 关联到请求中
				request.setResponse(singleResult);
			}
		}
	}

}
